home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-03 | 15.5 KB | 393 lines | [TEXT/KAHL] |
- /*
- ** CTerminalPane.cp
- **
- ** TerminalPane library
- ** Terminal display pane
- **
- ** Copyright © 1993–94, FrostByte Design / Eric Scouten
- **
- */
-
-
- #include "CTerminalPane.h"
-
- #include <Events.h>
- #include "CBureaucrat.h"
- #include "CScrollPane.h"
- #include "Global.h"
- #include "LongCoordinates.h"
- #include "LongQD.h"
-
-
-
- extern CBureaucrat* gGopher;
-
-
- #define resetInvalsChar 3
-
- TCL_DEFINE_CLASS_D1(CTerminalPane, CPanorama)
-
-
- // —— constructor ——
-
- /*______________________________________________________________________
- **
- ** constructors
- **
- ** Initialize the pane. Nothing special here. Parameters and usage are all the same
- ** as for CPanorama.
- **
- */
-
- CTerminalPane::CTerminalPane() : CPanorama()
- { CTerminalPaneX(); }
-
- CTerminalPane::CTerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
- short aWidth, short aHeight, short aHEncl, short aVEncl,
- SizingOption aHSizing, SizingOption aVSizing)
- : CPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing)
- { CTerminalPaneX(); }
-
- void CTerminalPane::ITerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
- short aWidth, short aHeight, short aHEncl, short aVEncl,
- SizingOption aHSizing, SizingOption aVSizing)
- {
- CPanorama::IPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing);
- if (member(itsEnclosure, CScrollPane))
- ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
- }
-
-
- /*______________________________________________________________________
- **
- ** CTerminalPaneX (private method)
- **
- ** Finish initialization for terminal pane.
- **
- */
-
- void CTerminalPane::CTerminalPaneX()
-
- {
- LongRect theBounds;
-
- SetLongRect(&theBounds, 0, 0, sizeX, sizeY);
- SetBounds(&theBounds);
- SetCanBeGopher(TRUE);
- SetWantsClicks(TRUE);
-
- if (member(itsEnclosure, CScrollPane))
- ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
-
- charsToInvalLine = resetInvalsChar;
- blinkCursor = FALSE;
- cursorVis = TRUE;
- lastCursorCol = lastCursorLine = 0;
- lastCursorTick = 0L;
- disableKeyScroll = FALSE;
- DoClearScreen();
- }
-
-
- // —— drawing ——
-
- /*______________________________________________________________________
- **
- ** Draw
- **
- ** Draw characters from the theScreen array onto the real screen.
- **
- ** area (Rect*): area to be redrawn (in frame coordinates)
- **
- */
-
- void CTerminalPane::Draw(Rect* area)
-
- {
- short left, top, right, bottom; // char coordinatates of draw region
- short dLine; // where to draw now
- LongRect theLongArea; // frame coordinates of region
- LongPt theLongPt;
- Point thePoint;
-
-
- // figure draw region
-
- charsToInvalLine = resetInvalsChar;
- QDToFrameR(area, &theLongArea);
- left = (theLongArea.left - offsetX) / pixelsX;
- right = (theLongArea.right -offsetX + 1) / pixelsX;
- top = (theLongArea.top - offsetY) / pixelsY;
- bottom = (theLongArea.bottom -offsetY + 1) / pixelsY;
-
-
- // do range checking
-
- left = TCLMax(left, 0);
- top = TCLMax(top, 0);
- right = TCLMin(right, maxX-1);
- bottom = TCLMin(bottom, maxY-1);
-
-
- // hard-wire for Monaco 9: Mom, don’t look at this code!
-
- TextFont(4);
- TextFace(0);
- TextSize(9);
-
-
- // draw the stuff
-
- if (left <= right) {
- dLine = top;
- while (dLine <= bottom) {
- SetLongPt(&theLongPt, left * pixelsX, dLine * pixelsY);
- FrameToQD(&theLongPt, &thePoint);
- MoveTo(thePoint.h + offsetX, thePoint.v + offsetY + pixelsY-2);
- DrawText(&theScreen[dLine][left], 0, right-left+1);
- dLine++;
- }
- }
-
-
- // check to see if we overwrote the cursor
-
- if ((left <= theColumn) && (right >= theColumn) &&
- (top <= theLine) && (bottom >= theLine) && cursorVis)
- InvertCursor(theColumn, theLine);
-
- }
-
-
- // —— blinking cursor support ——
-
- /*______________________________________________________________________
- **
- ** Dawdle
- **
- ** Blink the cursor if necessary. Cursor blinks at the user-defined rate for insertion point
- ** blinking.
- **
- ** maxSleep (long*): maximum sleep value, updated if necessary
- **
- */
-
- void CTerminalPane::Dawdle(long* maxSleep)
-
- {
- CPanorama::Dawdle(maxSleep);
- if (blinkCursor) {
- *maxSleep = TCLMin(*maxSleep, GetCaretTime());
- if (LMGetTicks() >= lastCursorTick + GetCaretTime()) {
- cursorVis = !cursorVis;
- lastCursorTick = LMGetTicks();
- InvalCharRect(theColumn, theLine, theColumn, theLine);
- }
- }
- }
-
-
- /*______________________________________________________________________
- **
- ** BecomeGopher
- **
- ** Become the gopher (or leave gopher status). All our routine does is force a refresh
- ** of the cursor.
- **
- ** fBecoming (Boolean): TRUE if becoming gopher
- **
- ** return (Boolean): TRUE if successful in changing status
- **
- */
-
- Boolean CTerminalPane::BecomeGopher(Boolean fBecoming)
-
- {
- if (!fBecoming)
- cursorVis = TRUE;
- InvalCharRect(theColumn, theLine, theColumn, theLine);
- return CPanorama::BecomeGopher(fBecoming);
- }
-
-
- /*______________________________________________________________________
- **
- ** SetBlinking
- **
- ** Turns on or off cursor blinking.
- **
- ** blinkMode (Boolean): TRUE to enable cursor blinking
- **
- */
-
- void CTerminalPane::SetBlinking(Boolean blinkMode)
-
- {
- blinkCursor = blinkMode;
- if ((blinkMode) && (gGopher == this)) {
- lastCursorCol = theColumn;
- lastCursorLine = theLine;
- CursorMoved();
- }
- else {
- cursorVis = TRUE;
- InvalCharRect(theColumn, theLine, theColumn, theLine);
- }
- }
-
-
- // —— scrolling ——
-
- /*______________________________________________________________________
- **
- ** ScrollToSelection
- **
- ** Ensure that the current cursor location is visible.
- **
- */
-
- void CTerminalPane::ScrollToSelection()
-
- {
- short hSpan, vSpan;
- LongRect topLeftRect, botRightRect; // top left / bottom right cells of selection
- // held over from CTable::ScrollToSelection
- // because we might implement character selection later
- LongPt selPos;
-
-
- // get current window parameters
-
- if (EmptyLongRect(&aperture)) // nothing selected or nothing visible
- return;
- GetFrameSpan(&hSpan, &vSpan);
- selPos = position; // init to current scroll position
-
-
- // figure out where cursor (or selection) is
-
- CalcCharRect(theColumn, theLine, theColumn, theLine, &topLeftRect);
- topLeftRect.left -= offsetX;
- topLeftRect.top -= offsetY;
- topLeftRect.right += offsetX;
- topLeftRect.bottom += offsetY;
- botRightRect = topLeftRect;
- // adapt later for charcter selections
-
-
- // calc vertical scroll
-
- if (topLeftRect.bottom >= position.v + vSpan) // Is the top of selection below the bottom of frame?
- selPos.v = topLeftRect.bottom - vSpan;
- else if (botRightRect.top < position.v) // Is the bottom of selection above the top of the frame?
- selPos.v = botRightRect.top;
-
-
- // calc horizontal scroll
-
- if (topLeftRect.right >= position.h + hSpan) // Is the left edge of selection past the right edge of frame?
- selPos.h = topLeftRect.right - hSpan;
- else if (botRightRect.left < position.h) // Is the right edge of selection before the left edge of frame?
- selPos.h = botRightRect.left;
-
- if ((selPos.h != position.h) || (selPos.v != position.v))
- ScrollTo(&selPos, TRUE);
-
- }
-
-
- /*______________________________________________________________________
- **
- ** DisableKeyScroll
- **
- ** Turn on or off keyboard scrolling commands.
- **
- ** disable (Boolean): TRUE to turn off keyboard scrolling
- **
- */
-
- void CTerminalPane::DisableKeyScroll(Boolean disable)
-
- {
- disableKeyScroll = disable;
- }
-
-
- /*______________________________________________________________________
- **
- ** DoKeyDown
- **
- ** Override to enable or disable key scrolling (which is implemented in CPanorama).
- **
- */
-
- void CTerminalPane::DoKeyDown(char theChar, Byte keyCode, EventRecord* macEvent)
-
- {
- if (disableKeyScroll)
- CBureaucrat::DoKeyDown(theChar, keyCode, macEvent);
- else
- CPanorama::DoKeyDown(theChar, keyCode, macEvent);
- }
-
-
- // —— terminal emulation methods ——
-
- /*______________________________________________________________________
- **
- ** DoClearScreen
- **
- ** Clear the screen and move the cursor to (0,0).
- **
- */
-
- void CTerminalPane::DoClearScreen()
-
- {
- register short x, y;
-
- theLine = theColumn = 0;
- CursorMoved();
-
- for (y = 0; y < maxY; ++y)
- for (x = 0; x < maxX; ++x)
- theScreen[y][x] = ' ';
- Refresh();
- }
-
-
- /*______________________________________________________________________
- **
- ** DoWriteChar
- **
- ** Write a character to the terminal. This method handles *basic* terminal emulation.
- ** To provide more sophisticated emulation, override this method.
- **
- ** theChar (char): the character to write
- **
- */
-
- void CTerminalPane::DoWriteChar(char theChar)
-
- {
-
- // parse a few control characters
-
- switch (theChar) {
-
- case charNUL:
- break;
-
- case charBEL:
- SysBeep(0);
- break;
-
- case charBS:
- if (theColumn > 0)
- theColumn--;
- CursorMoved();
- break;
-
- case charHT:
- theColumn = ((short) ((theColumn + 7) / 8)) * 8;
- if (the